package com.hontech.bv.http

import android.os.Environment
import com.hontech.bv.app.AppContext
import com.hontech.bv.utils.parseJson
import com.hontech.bv.utils.safeClose
import kotlinx.coroutines.CompletableDeferred
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.atomic.AtomicInteger

val DOWNLOAD_PROG = AtomicInteger(0)


class DownloadCallback(val name: String, private val promise: CompletableDeferred<File>) : Callback {

    override fun onFailure(call: Call, e: IOException) {
        promise.completeExceptionally(e)
    }

    private fun parseResp(response: Response) {
        val statusCode = response.code
        if (statusCode != 200) {
            throw IOException("响应头错误:$statusCode")
        }

        val body = response.body ?: throw IOException("没有响应内容")

        val head = response.header(Http.HEAD_RESP, Http.RESP_FAIL)

        if ((head == null) || (head == Http.RESP_FAIL)) {
            val buf = body.bytes()
            val errResp = parseJson<ErrResp>(buf)
            throw IOException(errResp.errMsg)
        }

        val dir = AppContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) ?: throw IOException("无法获取下载目录")
        if ((!dir.exists()) && (!dir.mkdirs())) {
            throw IOException("无法创建下载目录")
        }
        val size = body.contentLength().toInt()

        val file = File(dir, name)
        val out = FileOutputStream(file, false)
        val input = body.byteStream()
        var index = 0
        input.use {
            val buf = ByteArray(4096)
            while (true) {
                val n = input.read(buf)
                if (n <= 0) {
                    break
                }
                out.write(buf, 0, n)
                index += n

                DOWNLOAD_PROG.set(index * 100 / size)
            }
        }
        out.safeClose()
        if (index != size) {
            throw IOException("下载文件异常 长度错误")
        }
        promise.complete(file)
    }

    override fun onResponse(call: Call, response: Response) {
        try {
            parseResp(response)
        } catch (e: Exception) {
            promise.completeExceptionally(e)
        }
    }
}
